package com.ruicar.afs.cloud.product.controller;

import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ruicar.afs.cloud.bizcommon.algorithm.service.AfsAlgorithmService;
import com.ruicar.afs.cloud.bizcommon.algorithm.service.FinanceCalculatorService;
import com.ruicar.afs.cloud.bizcommon.business.bean.AfsRepaymentInfo;
import com.ruicar.afs.cloud.bizcommon.business.bean.FinanceCalculatorBean;
import com.ruicar.afs.cloud.bizcommon.business.bean.FinanceInfoBean;
import com.ruicar.afs.cloud.bizcommon.business.dto.CalMeasureDTO;
import com.ruicar.afs.cloud.bizcommon.business.dto.CalculatorDTO;
import com.ruicar.afs.cloud.bizcommon.business.dto.CalculatorListDTO;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinCostDetails;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinDiscountDetails;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinRentAdjustDetails;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyCostDetailsService;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyDiscountDetailsService;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyRentAdjustDetailsService;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.parameter.commom.enums.CostType;
import com.ruicar.afs.cloud.parameter.commom.enums.WhetherEnum;
import com.ruicar.afs.cloud.product.condition.ProductMeasureInfoCondition;
import com.ruicar.afs.cloud.product.dto.CheckProductInfoDto;
import com.ruicar.afs.cloud.product.entity.*;
import com.ruicar.afs.cloud.product.enums.ProductOnlineStatus;
import com.ruicar.afs.cloud.product.enums.StatusEnum;
import com.ruicar.afs.cloud.product.enums.TemplateCategory;
import com.ruicar.afs.cloud.product.service.*;
import com.ruicar.afs.cloud.product.vo.CheckCostInfoVo;
import com.ruicar.afs.cloud.product.vo.ExtrasProgramInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author yaorui.zhang
 * @version 1.0
 * @date 2020/5/11 20:46
 */
@Slf4j
@RestController
@AllArgsConstructor
@Api("产品测算接口")
@RequestMapping("/product")
public class ProductMeasureController {

    private ApplyCostDetailsService costDetailsService;
    private ApplyDiscountDetailsService discountDetailsService;
    private ApplyRentAdjustDetailsService rentAdjustDetailsService;
    private ProductPlanService productPlanService;
    private AfsAlgorithmService afsAlgorithmService;
    private FinanceCalculatorService financeCalculatorService;
    private ProductMeasureInfoService productMeasureInfoService;
    private ProductMeasurePlanService productMeasurePlanService;
    private final ExtrasProjectService extrasService;
    private final ExtrasProgramConfigService extrasProgramConfigService;

    /**
     * 查询产品列表
     *
     * @param condition
     * @return
     */
    @PostMapping(value = "/queryProductSelectList")
    @ApiOperation("查询产品列表")
    public IResponse queryProductSelectList(@RequestBody CalculatorDTO condition) {
        IPage<ProductPlan> productPlanList = productPlanService.page(new Page(condition.getPageNo(), condition.getPageSize()), (Wrapper<ProductPlan>) Wrappers.<ProductPlan>query().lambda()
                .eq(ProductPlan::getIsModel, AfsEnumUtil.key(StatusEnum.NO))//产品
                .eq(ProductPlan::getTemplateCategory, AfsEnumUtil.key(TemplateCategory.Father))//主产品
                .ne(ProductPlan::getStatus, AfsEnumUtil.key(ProductOnlineStatus.TEMPORARY_STORAGE))//状态不等于暂存
                .ne(ProductPlan::getStatus, AfsEnumUtil.key(ProductOnlineStatus.OFFLINE))//状态不等于下线
                .like(StringUtil.isNotEmpty(condition.getProductName()),ProductPlan::getProductName,condition.getProductName())//产品名称
        );
        return IResponse.success(productPlanList);
    }

    /**
     * 查询产品详情
     *
     * @param condition
     * @return
     */
    @PostMapping(value = "/queryProductDetails")
    @ApiOperation("查询产品详情")
    public IResponse queryProductDetails(@ModelAttribute CheckProductInfoDto info) {
        Map map = productPlanService.getProductDetails(info);
        return IResponse.success(map);
    }

    /**
     * 获取产品利率
     *
     * @return
     */
    @ApiOperation("获取产品利率")
    @PostMapping(value = "/getProductRate")
    public IResponse getProductRate(@ModelAttribute CalculatorDTO condition) {

        String applyNo = condition.getApplyNo();
        CheckProductInfoDto dto = new CheckProductInfoDto();
        dto.setId(condition.getId());
        // 利率信息
        if (CostType.CARAMT.getIndex().equals(condition.getCostType())) {
            CheckCostInfoVo mainProductInfo = new CheckCostInfoVo();
            mainProductInfo.setProductId(condition.getId());
            mainProductInfo.setLoanTerm(condition.getLoanTerm());
            dto.setMainProductInfo(mainProductInfo);
        } else if (CostType.AFFIXAMT.getIndex().equals(condition.getCostType())) {
            CheckCostInfoVo addProductInfo = new CheckCostInfoVo();
            addProductInfo.setLoanTerm(condition.getLoanTerm());
            addProductInfo.setProductId(condition.getAddId());
            dto.setAddProductInfo(addProductInfo);
        }

        JSONObject result = productPlanService.getcustomerrate(dto);
        return IResponse.success(result);
    }

    /**
     * 查询贷款信息【汇总】
     *
     * @param condition
     * @return
     */
    @PostMapping(value = "/getFinanceCostAll")
    @ApiOperation("查询贷款信息【汇总】")
    public IResponse getFinanceCostAll(@ModelAttribute CalculatorDTO condition) {

        FinanceCalculatorBean vo = new FinanceCalculatorBean();
        String applyNo = condition.getApplyNo();
        // 合计信息
        costDetailsService.getFinanceCostTotal(vo, condition);
        // 附加产品
        String isAdditional = WhetherEnum.No.getIndex();
        FinanceInfoBean addProductInfo = costDetailsService.getAddProductInfo(applyNo, condition.getCarId(), CostType.AFFIXAMT.getIndex());
        if (addProductInfo != null) {
            isAdditional = WhetherEnum.YES.getIndex();
            vo.setIsAdditional(isAdditional);
            vo.setAddProductInfo(addProductInfo);
        }
        // 车辆产品
        FinanceInfoBean carProductInfo = costDetailsService.getCarProductInfo(applyNo, condition.getCarId(), CostType.CARAMT.getIndex());
        // 是否有子产品
        if (carProductInfo != null) {
            String isSubProduct = carProductInfo.getCostInfo().getIsSubProduct();
            if (WhetherEnum.No.getIndex().equals(isSubProduct)) {
                isAdditional = WhetherEnum.YES.getIndex();
                vo.setIsAdditional(isAdditional);
            }
            vo.setIsSubProduct(isSubProduct);
        }
        vo.setCarProductInfo(carProductInfo);

        // 租金调整
        List<FinRentAdjustDetails> rentList = rentAdjustDetailsService.getRentAdjustDetails(condition.getApplyNo());
        if (rentList != null && rentList.size() > 0) {
            vo.setRentList(rentList);
        }

        return IResponse.success(vo);
    }

    /**
     * 查询贴息明细列表
     *
     * @param condition
     * @return
     */
    @PostMapping(value = "/getDiscountDetails")
    @ApiOperation("查询贴息明细列表")
    public IResponse getDiscountDetails(@ModelAttribute CalculatorDTO condition) {

        List<FinDiscountDetails> discountList = discountDetailsService.getDiscountDetailsList(condition.getApplyNo(), condition.getCostType());
        return IResponse.success(discountList);
    }

    /**
     * 保存融资信息
     *
     * @param condition
     * @return
     */
    @PostMapping(value = "/saveCostList")
    @ApiOperation("保存融资信息")
    @Transactional(rollbackFor = Exception.class)
    public IResponse saveCostList(@RequestBody CalculatorListDTO condition) {
        //保存测算信息
        ProductMeasureInfo productMeasureInfo = new ProductMeasureInfo();
        productMeasureInfo.setMeasureCoefficient(condition.getMeasureCoefficient());//测算系数
        productMeasureInfo.setMeasureIrr(condition.getMeasureIrr());//IRR测算值
        productMeasureInfoService.save(productMeasureInfo);
        //循环保存还款计划表
        for (AfsRepaymentInfo afsRepaymentInfo : condition.getRepaymentInfoList()) {
            //初始化
            ProductMeasurePlan productMeasurePlan = new ProductMeasurePlan();
            //复制
            BeanUtils.copyProperties(afsRepaymentInfo, productMeasurePlan);
            //塞入测算ID
            productMeasurePlan.setMeasureId(productMeasureInfo.getId());
            //保存
            productMeasurePlanService.save(productMeasurePlan);
        }
        //测算ID作为申请编号
        String applyNo = productMeasureInfo.getId().toString();
        //保存融资信息
        List<FinCostDetails> resultList = costDetailsService.saveCostDetailsList(applyNo, null, condition.getCostList());

        //二次保存测算信息
        FinCostDetails finCostDetails = costDetailsService.getOne(Wrappers.<FinCostDetails>query().lambda()
                        .eq(FinCostDetails::getApplyNo, applyNo)
                , false
        );
        productMeasureInfo.setLoanAmt(finCostDetails.getLoanAmt());
        productMeasureInfo.setLoanTerm(finCostDetails.getLoanTerm());
        productMeasureInfo.setProductId(Long.parseLong(finCostDetails.getProductId()));
        productMeasureInfo.setProductName(finCostDetails.getProductName());
        productMeasureInfoService.updateById(productMeasureInfo);

        return IResponse.success(resultList);
    }

    /**
     * 更新融资信息
     *
     * @param condition
     * @return
     */
    @PostMapping(value = "/updateCostList")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("更新融资列表")
    public IResponse updateCostList(@RequestBody CalculatorListDTO condition) {

        String applyNo = condition.getApplyNo();
        List<FinCostDetails> resultList = costDetailsService.updateCostDetailsList(applyNo, null, condition.getCostList());
        return IResponse.success(resultList);
    }

    /**
     * 调用计算器生成多个还款计划表
     *
     * @param condition
     * @return
     */
    @ApiOperation("调用计算器")
    @PostMapping("/financeCalculation")
    public IResponse financeCalculation(@RequestBody CalculatorListDTO condition) {

        return financeCalculatorService.getMultipleRepaymentPlan(condition.getCostList());
    }

    /**
     * 通过贴息金额倒推客户利率
     *
     * @param condition
     * @return
     */
    @ApiOperation("通过贴息金额倒推客户利率")
    @PostMapping("/getCustRate")
    public IResponse getCustRate(@RequestBody CalculatorDTO condition) {

        return afsAlgorithmService.getCustomerRate(condition);
    }

    /**
     * 获取任意贷还款计划表
     *
     * @return
     */
    @ApiOperation("获取任意贷还款计划表")
    @PostMapping("/getArbitraryRepaymentPlan")
    public IResponse getArbitraryRepaymentPlan(@RequestBody CalculatorDTO condition) {

        return financeCalculatorService.getSingleRepaymentPlan(condition);
    }

    @PostMapping(value = "/calculateIrr")
    @ApiOperation("测算IRR")
    public IResponse calculateIrr(@RequestBody CalMeasureDTO condition) {

        String irrString = "-" + condition.getTotalLoanAmt() + ",";
        List<AfsRepaymentInfo> repaymentInfoList = condition.getRepaymentInfoList();
        for (AfsRepaymentInfo afsRepaymentInfo : repaymentInfoList) {
            irrString = irrString + afsRepaymentInfo.getYueGong().add(afsRepaymentInfo.getModifyAmount()) + ",";
        }
        BigDecimal irr = afsAlgorithmService.calIRR(irrString);
        irr = irr.multiply(condition.getMeasureCoefficient());
        return IResponse.success(irr);
    }

    @PostMapping(value = "/getMeasureInfoList")
    @ApiOperation(value = "多条件分页获取")
    public IResponse<IPage<ProductMeasureInfo>> getMeasureInfoList(@ModelAttribute ProductMeasureInfoCondition condition) {
        return IResponse.success(productMeasureInfoService.page(new Page(condition.getPageNumber(), condition.getPageSize()), Wrappers.<ProductMeasureInfo>query().lambda()
                .eq(ProductMeasureInfo::getProductId, condition.getProductId())
                .orderByDesc(ProductMeasureInfo::getCreateTime)
        ));
    }

    @PostMapping(value = "/getMeasureInfo")
    @ApiOperation(value = "根据ID查询")
    public IResponse<IPage<ProductMeasureInfo>> getMeasureInfo(@ModelAttribute ProductMeasureInfoCondition condition) {
        ProductMeasureInfo productMeasureInfo = productMeasureInfoService.getById(condition.getId());
        List<ProductMeasurePlan> list = productMeasurePlanService.list(Wrappers.<ProductMeasurePlan>query().lambda()
                .eq(ProductMeasurePlan::getMeasureId, condition.getId())
        );
        //组装数据返回
        JSONObject json = new JSONObject();
        json.put("productMeasureInfo", productMeasureInfo);
        json.put("list", list);

        return IResponse.success(json);
    }

    @PostMapping(value = "/delMeasureInfo")
    @ApiOperation(value = "根据ID删除")
    public IResponse delMeasureInfo(@ModelAttribute ProductMeasureInfoCondition condition) {
        productMeasureInfoService.removeById(condition.getId());
        return IResponse.success("删除成功");
    }

    /**
     * 查询产品列表
     *
     * @param condition
     * @return
     */
    @PostMapping(value = "/queryExtrasInfoSonList")
    @ApiOperation("查询产品ID对应的附加项目列表")
    public IResponse queryExtrasInfoSonList(@RequestBody ExtrasProgramInfoVo extrasInfo) {
        if(extrasInfo.getExtrasProgramId()!=null){
            List<ExtrasProjectProgramInfo> extrasProjectProgramInfos = extrasProgramConfigService.list(Wrappers.<ExtrasProjectProgramInfo>query().lambda()
                    .eq(ExtrasProjectProgramInfo::getExtrasPlanId,String.valueOf(extrasInfo.getExtrasProgramId()))
            );
            List extrasProjectProgramInfoIdList = Lists.transform(extrasProjectProgramInfos, (extrasProjectProgramInfo) -> {
                return extrasProjectProgramInfo.getExtrasProjectId();
            });
            List<ExtrasInfo> list = extrasService.list(Wrappers.<ExtrasInfo>query().lambda()
                    .eq(StringUtil.isNotEmpty(extrasInfo.getFatherNo()),ExtrasInfo::getFatherNo,extrasInfo.getFatherNo())
                    .in(ExtrasInfo::getId,extrasProjectProgramInfoIdList)
                    .like(StringUtil.isNotEmpty(extrasInfo.getExtrasProjectName()),ExtrasInfo::getExtrasProjectName,extrasInfo.getExtrasProjectName())
                    .orderByAsc());
            return IResponse.success(list);
        }else{
            return IResponse.fail("附加方案ID不可为空");
        }
    }


}
